﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace GameNode
{
    class Game
    {
        private Random rnd;
        private Drawer drawer;
        private List<Node> nodes;
        private List<Node> winnerNodes;
        private Node targetNode;

        public void StartGame(int borderWidth, int borderHeight, int startX, int startY, char borderSymbol,
                              ConsoleColor borderColor, int amountOfNodes, char targetNodeSymbol, ConsoleColor targetNodeColor)
        {
            Console.CursorVisible = false;
            rnd = new Random();
            drawer = new Drawer();
            nodes = new List<Node>();
            winnerNodes = new List<Node>();

            targetNode = GenerateRandomTargetNode(borderWidth, borderHeight, startX, startY, targetNodeSymbol, targetNodeColor);
            drawer.DrawNode(targetNode);

            GenereateRandomNodes(borderWidth, borderHeight, startX, startY, amountOfNodes);

            bool isGameOver = false;
            do
            {
                bool isNewRound = false;
                Console.Clear();
                Console.SetCursorPosition(0, 0);
                drawer.DrawBorder(borderWidth, borderHeight, startX, startY, borderSymbol, borderColor);
                do
                {
                    
                    for (int j = 0; j < nodes.Count; j++)
                    {
                        switch (rnd.Next(1, 5))
                        {
                            case 1:
                                {
                                    if (IsOnBorder(nodes[j].X + 1, nodes[j].Y, drawer) == false && IsOnNode(nodes[j].X + 1, nodes[j].Y, nodes) == false)
                                    {
                                        nodes[j].MoveRight();
                                    }
                                    break;
                                }
                            case 2:
                                {
                                    if (IsOnBorder(nodes[j].X - 1, nodes[j].Y, drawer) == false && IsOnNode(nodes[j].X - 1, nodes[j].Y, nodes) == false)
                                    {
                                        nodes[j].MoveLeft();
                                    }
                                    break;
                                }
                            case 3:
                                {
                                    if (IsOnBorder(nodes[j].X, nodes[j].Y + 1, drawer) == false && IsOnNode(nodes[j].X, nodes[j].Y + 1, nodes) == false)
                                    {
                                        nodes[j].MoveDown();
                                    }
                                    break;
                                }
                            case 4:
                                {
                                    if (IsOnBorder(nodes[j].X, nodes[j].Y - 1, drawer) == false && IsOnNode(nodes[j].X, nodes[j].Y - 1, nodes) == false)
                                    {
                                        nodes[j].MoveUp();
                                    }
                                    break;
                                }
                        }
                        drawer.DrawNode(nodes[j]);
                        drawer.DrawNode(targetNode);

                        if (IsOnNode(targetNode.X, targetNode.Y, nodes) == true)
                        {
                            winnerNodes.Add(nodes[j]);
                            nodes.RemoveAt(j);
                            if (nodes.Count == 1)
                            {
                                drawer.DrawWinnerNodesAndMessage(winnerNodes, 5, "Winners");
                                drawer.DrawLooserNodesAndMessage(nodes, 15, "Looser");
                                isNewRound = true;
                            }
                        }
                    }
                    Thread.Sleep(100);

                    foreach (var node in nodes)
                    {
                        drawer.ClearNode(node);
                    }

                } while (!isNewRound);

                Console.ReadKey();

                if (winnerNodes.Count == 1)
                {
                    isGameOver = true;
                }
                else
                {
                    nodes = winnerNodes;
                    winnerNodes = new List<Node>();
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        char nodeSymbol = nodes[i].NodeSymbol;
                        ConsoleColor color = nodes[i].Color;
                        nodes[i] = new Node(rnd.Next(startX + 1, startX + borderWidth - 2), rnd.Next(startY + 1, startY + borderHeight - 2), color, nodeSymbol);
                    }
                }

            } while (!isGameOver);
        }

        private Node GenerateRandomTargetNode(int borderWidth, int borderHeight, int startX, int startY, char targetNodeSymbol, ConsoleColor targetNodeColor)
        {
            return new Node(rnd.Next(startX + 1, startX + borderWidth - 2), rnd.Next(startY + 1, startY + borderHeight - 2), targetNodeColor, targetNodeSymbol);
        }

        private void GenereateRandomNodes(int borderWidth, int borderHeight, int startX, int startY, int amountOfNodes)
        {
            int charPosition = 0;
            bool positionFree = true;
            char[] chars = "@#$%&".ToCharArray();

            do
            {
                if (IsOnNode(rnd.Next(startX + 1, startX + borderWidth - 2), rnd.Next(startY + 1, startY + borderHeight - 2), nodes) == false && IsOnNode(targetNode.X, targetNode.Y, nodes) == false)
                {
                    positionFree = true;
                }
                if (charPosition <= chars.Length - 1)
                {
                    if (positionFree == true)
                    {
                        nodes.Add(new Node(rnd.Next(startX + 1, startX + borderWidth - 2), rnd.Next(startY + 1, startY + borderHeight - 2), (ConsoleColor)rnd.Next(1, 16), chars[charPosition]));
                        charPosition++;
                    }
                }
                if (charPosition > chars.Length - 1)
                {
                    charPosition = 0;
                }
                positionFree = false;
            } while (nodes.Count < amountOfNodes);
        }

        public bool IsOnNode(int x, int y, List<Node> nodes)
        {
            foreach (var node in nodes)
                if (x == node.X && y == node.Y)
                    return true;
            return false;
        }

        public bool IsOnBorder(int x, int y, Drawer drawer)
        {
            if ((x == drawer.X + drawer.width - 1) || (x == drawer.X) || (y == drawer.Y + drawer.height - 1) || (y == drawer.Y))
                return true;
            return false;
        }
    }
}
